package com.javabi.common.collect.indexmap;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

class ImmutableList<V> implements List<V> {

	private final V[] array;

	public ImmutableList(V[] array) {
		this.array = array;
	}

	@Override
	public int size() {
		return array.length;
	}

	@Override
	public boolean isEmpty() {
		return array.length == 0;
	}

	@Override
	public boolean contains(Object object) {
		return indexOf(object) != -1;
	}

	@Override
	public V get(int index) {
		throw new UnsupportedOperationException();
	}

	@Override
	public int indexOf(Object object) {
		for (int i = 0; i < array.length; i++) {
			if (array[i].equals(object)) {
				return i;
			}
		}
		return -1;
	}

	@Override
	public int lastIndexOf(Object object) {
		for (int i = array.length - 1; i >= 0; i--) {
			if (array[i].equals(object)) {
				return i;
			}
		}
		return -1;
	}

	@Override
	public Iterator<V> iterator() {
		return new ImmutableListIterator<V>(array);
	}

	@Override
	public ListIterator<V> listIterator() {
		return new ImmutableListIterator<V>(array);
	}

	@Override
	public boolean containsAll(Collection<?> collection) {
		for (Object object : collection) {
			if (!contains(object)) {
				return false;
			}
		}
		return true;
	}

	@Override
	public int hashCode() {
		int hashCode = 1;
		Iterator<V> i = iterator();
		while (i.hasNext()) {
			V obj = i.next();
			hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
		}
		return hashCode;
	}

	@Override
	@SuppressWarnings("rawtypes")
	public boolean equals(Object o) {
		if (o == this)
			return true;
		if (!(o instanceof List))
			return false;

		ListIterator<V> e1 = listIterator();
		ListIterator e2 = ((List) o).listIterator();
		while (e1.hasNext() && e2.hasNext()) {
			V o1 = e1.next();
			Object o2 = e2.next();
			if (!(o1 == null ? o2 == null : o1.equals(o2)))
				return false;
		}
		return !(e1.hasNext() || e2.hasNext());
	}

	@Override
	public String toString() {
		return Arrays.toString(array);
	}

	@Override
	public Object[] toArray() {
		return Arrays.copyOf(array, array.length);
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T[] toArray(T[] newArray) {
		int size = array.length;
		if (newArray.length < size)
			// Make a new array of a's runtime type, but my contents:
			return (T[]) Arrays.copyOf(array, size, newArray.getClass());
		System.arraycopy(array, 0, newArray, 0, size);
		if (newArray.length > size)
			newArray[size] = null;
		return newArray;
	}

	@Override
	public boolean add(V e) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean remove(Object o) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean addAll(Collection<? extends V> c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean addAll(int index, Collection<? extends V> c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void clear() {
		throw new UnsupportedOperationException();
	}

	@Override
	public V set(int index, V element) {
		throw new UnsupportedOperationException();
	}

	@Override
	public void add(int index, V element) {
		throw new UnsupportedOperationException();
	}

	@Override
	public V remove(int index) {
		throw new UnsupportedOperationException();
	}

	@Override
	public ListIterator<V> listIterator(int index) {
		throw new UnsupportedOperationException();
	}

	@Override
	public List<V> subList(int fromIndex, int toIndex) {
		throw new UnsupportedOperationException();
	}

}
